﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using Netcare.Core;

namespace Netcare.Web.Host.NT
{
    public class AspHost
    {
        public static Asp Create(int port, string vpath, string ppath)
        {
            Log.WriteInfo("Try to create http server, port={0}, virtualDir={1}, physicalDir={2}",
                port, vpath, ppath);
            Asp host = (Asp)ApplicationHost.CreateApplicationHost(
                typeof(Asp),
                vpath,
                ppath);

            host.Initialize(null, port, vpath, ppath);
            return host;
        }
    }

    public class Asp : MarshalByRefObject, IWebHost
    {
        private HttpListener listener;
        private Thread worker;

        public Asp()
        {
            App.InitializeAppDomainAndLogger("_0");

            listener = new HttpListener();
            worker = new Thread(ProcessRequestWorker);
        }

        public void Initialize(object app, int port, string vpath, string ppath)
        {
            listener.Prefixes.Clear();
            listener.Prefixes.Add(String.Format("http://+:{0}/", port));
        }

        public void Start()
        {
            if (listener.IsListening)
                throw new Exception("Host has already been listening");

            listener.Start();
            worker.Start();
            Log.WriteInfo("Http server started");
        }
        public void Stop()
        {
            if (!listener.IsListening)
                throw new Exception("Host is not in listening state");

            // shall we really abort the working thread?
            if (worker.IsAlive)
                worker.Abort();

            listener.Stop();
            Log.WriteInfo("Http server stopped");
        }

        private void ProcessRequest()
        {
            //use the ASP.NET HTTP pipeline to process request
            HttpListenerContext ctx = listener.GetContext();
            string page = ctx.Request.Url.LocalPath.TrimStart('/');
            string query = ctx.Request.Url.Query.TrimStart('?');

            Log.WriteInfo(ctx.Request.HttpMethod + " " + ctx.Request.Url.ToString());

            try
            {
                HttpRuntime.ProcessRequest(new HttpListenerWorkerRequest(ctx));
            }
            catch (Exception e)
            {
                Log.WriteException(e, "Error occured on processing page.");
            }

        }

        private void ProcessRequestWorker()
        {
            while (listener.IsListening)
                ProcessRequest();
        }
    }

}
